#ifndef __TRI_MESH_H__
#define __TRI_MESH_H__

#pragma once

#include "RenderMesh.h"

namespace Nezha
{

	struct NEZHA_ENGINE_ENTRY _Triangle
	{
		u32 index1;
		u32 index2;
		u32 index3;
	};

	class NEZHA_ENGINE_ENTRY TriMesh : public RenderMesh
	{
		friend class RenderObject;
	public:
		virtual ~TriMesh();

		virtual u32 getNumTriangles() const = 0;

	protected:
		bool getTriangle(u32 i, _Triangle& tri, int* indices) const
		{
			return getTriangle(i, tri.index1, tri.index2, tri.index3, indices);
		}

		virtual bool getTriangle(u32 i, u32& i1, u32& i2, u32& i3, int* indices) const = 0;

		virtual void updateNormals();
		virtual void updateTangents(u32 tangentSpace);

		TriMesh(GeometryData* gd);
	};

	/**
	@brief
		default triangle list mesh.
	*/
	class NEZHA_ENGINE_ENTRY TriangleListMesh : public TriMesh
	{
	public:
		GeometryType getType() const
		{
			return TRIANGLE_LIST;
		}

		TriangleListMesh(GeometryData* gd, bool recacuNormal = false);

		// override
		u32 getNumTriangles() const;

		static TriangleListMesh* CreatePlane(u32 xSamples, u32 ySamples, float w = 1.0f, float h = 1.0f);

		static TriangleListMesh* CreateBox(float w, float h, float depth);

		static TriangleListMesh* CreateSphere(u32 zSamples, u32 radialSamples, float r);

		struct Helper
		{
			VertexBufferAccessor::VertexElemBinding posVeb;
			VertexBufferAccessor::VertexElemBinding normVeb;
			VertexBufferAccessor::VertexElemBinding texVeb;
			VertexBufferAccessor::VertexElemBinding tex2Veb;
			VertexBufferAccessor::VertexElemBinding tangVeb;
			VertexBufferAccessor::VertexElemBinding binormVeb;
		};

		/** helper for create default triangleListMesh with default vertex decl */
		static void GetDefaultTLMVertexDecl(VertexDeclaration& vd);

		static void SetDefaultTLMVertexDcalMask(u32 vdMask);

	protected:
		bool getTriangle(u32 i, u32& i1, u32& i2, u32& i3, int* indices) const;
	};

	class NEZHA_ENGINE_ENTRY TriangleStripMesh : public TriMesh
	{
	public:
		GeometryType getType() const
		{
			return TRIANGLE_STRIP;
		}

		TriangleStripMesh(GeometryData* gd, bool recacuNormal = false);

		// override
		u32 getNumTriangles() const;

	protected:
		bool getTriangle(u32 i, u32& i1, u32& i2, u32& i3, int* indices) const;
	};

	typedef RefCountedPtr<TriMesh>::Default TriMeshPtr;
	typedef RefCountedPtr<TriangleListMesh>::Default TriListMeshPtr;

}//end namespace Nezha

#endif//end __TRI_MESH_H__